#include "memreuse.h"
#include <stdio.h>
#include <stdlib.h>
#include "udpresponse.h"

queue<mpz_t* > Memreuse::m_qmpz;
queue<element_t* > Memreuse::m_qG1Element;
queue<element_t* > Memreuse::m_qG2Element;
queue<element_t* > Memreuse::m_qGTElement;
queue<element_t* > Memreuse::m_qZrElement;
unsigned long Memreuse::m_nbits = 1024;
queue<UdpBlock *> Memreuse::m_qblock;
queue<Record *> Memreuse::m_qrecord;
pairing_t * Memreuse::m_pairing = NULL;

void Memreuse::InitializeBlocks(unsigned long size)
{
  for (unsigned long i = 0; i < size; i++)
	{
      UdpBlock * a = new UdpBlock;
      m_qblock.push(a);
	}
}

void Memreuse::InitializeRecords(unsigned long size)
{
  for (unsigned long i = 0; i < size; i++)
	{
      Record * a = new Record;
	  a->m_blocks.resize(3000, NULL);
	  for (int i = 0; i < 3000; i++)
		{
		  a->m_blocks[i] = new UdpBlock;
		}
      m_qrecord.push(a);
	}
}

void Memreuse::Initialize(unsigned long size, unsigned long nbits)
{
  m_nbits = nbits;
  for (unsigned long i = 0; i < size; i++)
	{
	  mpz_t * a = (mpz_t * ) malloc(sizeof(mpz_t) * 1);
	  mpz_init2( *a, nbits );
	  m_qmpz.push(a);
	}
}

void Memreuse::InitializeElements(unsigned long size, pairing_t * pairing)
{
  m_pairing = pairing;
  for (unsigned long i = 0; i < size; i++)
	{
	  element_t * a = (element_t * ) malloc(sizeof(element_t) * 1);
	  element_init_G1(*a, *m_pairing);
	  m_qG1Element.push(a);

	  element_t * b = (element_t * ) malloc(sizeof(element_t) * 1);
	  element_init_G2(*b, *m_pairing);
	  m_qG2Element.push(b);

	  element_t * c = (element_t * ) malloc(sizeof(element_t) * 1);
	  element_init_GT(*c, *m_pairing);
	  m_qGTElement.push(c);

	  element_t * r = (element_t * ) malloc(sizeof(element_t) * 1);
	  element_init_Zr(*r, *m_pairing);
	  m_qZrElement.push(r);
	}
}

mpz_t * Memreuse::New()
{
  if ( m_qmpz.size() == 0 )  
	{
	  mpz_t * a = (mpz_t * ) malloc(sizeof(mpz_t));
	  mpz_init2( *a, m_nbits );
	  m_qmpz.push(a);
	}

  mpz_t * ret = m_qmpz.front();
  m_qmpz.pop();
  return ret;
}

element_t * Memreuse::NewElement()
{
  element_t * a = (element_t * ) malloc(sizeof(element_t) * 1);
  return a;
}

element_t * Memreuse::NewG1Element()
{
  assert(m_pairing != NULL);
  if ( m_qG1Element.size() == 0 )  
	{
	  element_t * a = (element_t * ) malloc(sizeof(element_t) * 1);
	  element_init_G1(*a, *m_pairing);
	  m_qG1Element.push(a);
	}

  element_t * ret = m_qG1Element.front();
  m_qG1Element.pop();
  return ret;
}

element_t * Memreuse::NewG2Element()
{
  assert(m_pairing != NULL);
  if ( m_qG2Element.size() == 0 )  
	{
	  element_t * b = (element_t * ) malloc(sizeof(element_t) * 1);
	  element_init_G2(*b, *m_pairing);
	  m_qG2Element.push(b);
	}

  element_t * ret = m_qG2Element.front();
  m_qG2Element.pop();
  return ret;
}

element_t * Memreuse::NewGTElement()
{
  assert(m_pairing != NULL);
  if ( m_qGTElement.size() == 0 )  
	{
	  element_t * c = (element_t * ) malloc(sizeof(element_t) * 1);
	  element_init_GT(*c, *m_pairing);
	  m_qGTElement.push(c);
	}

  element_t * ret = m_qGTElement.front();
  m_qGTElement.pop();
  return ret;
}

element_t * Memreuse::NewZrElement()
{
  assert(m_pairing != NULL);
  if ( m_qZrElement.size() == 0 )  
	{
	  element_t * r = (element_t * ) malloc(sizeof(element_t) * 1);
	  element_init_Zr(*r, *m_pairing);
	  m_qZrElement.push(r);
	}

  element_t * ret = m_qZrElement.front();
  m_qZrElement.pop();
  return ret;
}


void Memreuse::Delete(mpz_t*& mpz)
{
  if (mpz != NULL)
	{
	  m_qmpz.push(mpz);
	  mpz = NULL;
	}
}

void Memreuse::DeleteG1Element(element_t*& element)
{
  if (element != NULL)
	{
	  m_qG1Element.push(element);
	  element = NULL;
	}
}

void Memreuse::DeleteG2Element(element_t*& element)
{
  if (element != NULL)
	{
	  m_qG2Element.push(element);
	  element = NULL;
	}
}

void Memreuse::DeleteGTElement(element_t*& element)
{
  if (element != NULL)
	{
	  m_qGTElement.push(element);
	  element = NULL;
	}
}

void Memreuse::DeleteZrElement(element_t*& element)
{
  if (element != NULL)
	{
	  m_qZrElement.push(element);
	  element = NULL;
	}
}


UdpBlock * Memreuse::NewBlock()
{
  if ( m_qblock.size() == 0 )  
	{
      UdpBlock * a = new UdpBlock;
	  m_qblock.push(a);
	  cerr<<"block size not enough"<<endl;
	}

  UdpBlock * ret = m_qblock.front();
  m_qblock.pop();
  return ret;
}

Record * Memreuse::NewRecord()
{
  if ( m_qrecord.size() == 0 )  
	{
      Record * a = new Record;
	  m_qrecord.push(a);
      cerr<<"record not enough"<<endl;
	}

  Record * ret = m_qrecord.front();
  m_qrecord.pop();
  return ret;
  
}


void Memreuse::Delete(UdpBlock*& pblock)
{
  if (pblock != NULL)
    {
      m_qblock.push(pblock);
      pblock = NULL;
    }
}


void Memreuse::Delete(Record*& precord)
{
  if (precord != NULL)
    {
      m_qrecord.push(precord);
      precord = NULL;
    }
}

